from flask import g, redirect, url_for, render_template, request, jsonify, session, abort
from info import db, constants
import logging
from info.models import Category, News, User
from info.response_code import RET
from info.utils.common import user_login_data
from info.utils.file_storage import upload_file
from . import user_blue


@user_blue.route('/info')
@user_login_data
def user_info():
    """用户中心主页"""
    user = g.user
    if not user:
        return redirect(url_for('index.index'))

    context = {
        'user': user.to_dict()
    }
    return render_template('news/user.html', context=context)


@user_blue.route('/base_info', methods=['GET', 'POST'])
@user_login_data
def base_info():
    """
    用户基本信息
    1.获取用户信息
    2.判断请求方式（get请求是加载用户信息，post请求是设置用户信息）
    3.get请求直接返回模板，渲染
    4.post请求需获取参数（nick_name， signature， gender）
    5.校验参数是否齐全，gender是否在范围内
    6.更新数据库的用户资料，同步到数据库
    7.重新设置session中的nick_name
    8.返回响应结果
    """
    user = g.user
    if request.method == 'GET':
        context = {
            'user': user.to_dict()
        }
        return render_template('news/user_base_info.html', context=context)

    json_dict = request.json
    nick_name = json_dict.get('nick_name')
    signature = json_dict.get('signature')
    gender = json_dict.get('gender')
    if not all([nick_name, signature, gender]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if gender not in ['MAN', 'WOMAN']:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    user.nick_name = nick_name
    user.signature = signature
    user.gender = gender
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='存储数据失败')
    # 将保存在session中的数据进行实时更新
    session['nick_name'] = nick_name
    return jsonify(errno=RET.OK, errmsg='OK')


@user_blue.route('/pass_info', methods=['GET', 'POST'])
@user_login_data
def pass_info():
    """
    修改密码
    1.判断请求方式，get请求则返回到密码修改模板，post请求则获取参数，进行密码修改
    2.获取用户信息
    3.获取参数（输入的原始密码，新密码）
    4.校验参数是否齐全
    5.用输入的原始密码与原始密码作比较（用user的check_password属性校验原始密码是否正确）
    6.原始密码校验正确，将新密码存储到数据库中
    7.返回响应
    """
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')

    json_dict = request.json
    old_password = json_dict.get('old_password')
    new_password = json_dict.get('new_password')
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    user = g.user
    if not user.check_password(old_password):
        return jsonify(errno=RET.PARAMERR, errmsg='原始密码错误')
    user.password = new_password
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='设置新密码失败')
    return jsonify(errno=RET.OK, errmsg='OK')


@user_blue.route('/user_collection')
@user_login_data
def user_collection():
    """
    用户收藏新闻页面
    1.获取参数（获取用户在看第几页,默认为第一页）
    2.获取用户信息
    3.查询登录用户收藏了哪些新闻（以分页的方式查询）
    4.构造响应数据
    5.渲染模板
    """
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        logging.error(e)
        page = 1
    user = g.user
    news_list = []
    current_page = 1
    total_page = 1
    try:
        paginate = user.collection_news.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        logging.error(e)
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())

    context = {
        'news_dict_list': news_dict_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_collection.html', context=context)


@user_blue.route('/pic_info', methods=['GET', 'POST'])
@user_login_data
def pic_info():
    """
    上传用户头像
    1.获取用户信息
    2.判断请求方式，get请求直接返回模板渲染头像，post请求则接收参数，设置新头像
    3.post请求接收参数
    4.读取图片
    5.上传图片
    6.保存图片上传后的唯一标识
    7.返回响应
    """
    user = g.user
    if request.method == 'GET':
        context = {
            'user': user.to_dict()
        }
        return render_template('news/user_pic_info.html', context=context)

    try:
        avatar_data = request.files.get('avatar').read()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='获取文件失败')
    # 上传文件到七牛云
    try:
        key = upload_file(avatar_data)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传文件失败')
    # 将图片的唯一标识存进数据库中
    user.avatar_url = key
    try:
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='存储数据库失败')
    data = {
        'avatar_url': constants.QINIU_DOMIN_PREFIX + key
    }
    return jsonify(errno=RET.OK, errmsg='设置头像成功', data=data)


@user_blue.route('/news_release', methods=['GET', 'POST'])
@user_login_data
def news_release():
    """
    用户新闻发布
    1.判断请求方式，get请求则查询出所有的分类信息渲染到模板中，post请求则获取参数，发布新闻
    2.获取参数（新闻标题，分类id，新闻摘要，索引图片，新闻内容）
    3.校验参数是否齐全
    4.读取图片文件
    5.将图片上传到七牛云
    6.同步数据库
    7.返回响应
    """
    if request.method == 'GET':
        categories = []
        try:
            categories = Category.query.all()
        except Exception as e:
            logging.error(e)
        categories_dicts = []
        for category in categories:
            category_dict = category.to_dict()
            categories_dicts.append(category_dict)
        # 移除“最新”分类
        categories_dicts.pop(0)
        context = {
            'categories': categories_dicts
        }
        return render_template('news/user_news_release.html', context=context)

    user = g.user
    # json_dict = request.json
    title = request.form.get('title')
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    index_image = request.files.get('index_image')
    content = request.form.get("content")
    source = "个人发布"
    if not all([title, category_id, digest, index_image, content, source]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    # 读取图片的二进制数据
    try:
        index_image = index_image.read()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='图片读取失败')
    # 将图片上传到七牛云
    try:
        key = upload_file(index_image)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片失败')
    # 创建新的新闻对象
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + key
    news.content = content
    news.source = source
    news.user_id = user.id
    # 设置状态为审核状态
    news.status = 1

    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='存储数据库失败')
    return jsonify(errno=RET.OK, errmsg='发布成功，等待审核')


@user_blue.route('/news_list')
@user_login_data
def news_list():
    """
    用户中心用户发布新闻列表
    1.获取参数（获取用户在看第几页,默认为第一页）
    2.获取用户信息
    3.查询登录用户发布了哪些新闻（以分页的方式查询）
    4.构造响应数据
    5.渲染模板
    """
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        logging.error(e)
        page = 1
    user = g.user
    news_list = []
    current_page = 1
    total_page = 1
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.USER_NEWS_RELEASE_MAX_COUNT, False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        logging.error(e)
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())

    context = {
        'news_dict_list': news_dict_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_news_list.html', context=context)


@user_blue.route('/user_follow')
@user_login_data
def user_follow():
    """
    用户关注的页面
    1.获取参数（获取用户在看第几页，默认为第一页）
    2.获取用户信息
    3.查询用户关注了哪些用户（以分页的方式查询）
    4.构造响应数据
    5.返回响应数据
    """
    page = request.args.get('p', 1)
    try:
        page = int(page)
    except Exception as e:
        logging.error(e)
        page = 1
    user = g.user
    follows_list = []
    current_page = 1
    total_page = 1
    try:
        paginate = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)
        follows_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        logging.error(e)
    follows_dict_list = []
    for follow in follows_list:
        follows_dict_list.append(follow.to_dict())
    context = {
        'follows_dict_list': follows_dict_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_follow.html', context=context)


@user_blue.route('/other_info')
@user_login_data
def other_info():
    """
    其他用户的详情页面
    1.获取用户信息
    2.获取其他用户的id
    3.查询其他用户信息
    4.判断当前用户是否关注此用户
    5.构造响应数据
    6.返回响应数据
    """
    user = g.user
    other_user_id = request.args.get('id')
    if not other_user_id:
        abort(404)
    other_user = None
    try:
        other_user = User.query.get(other_user_id)
    except Exception as e:
        logging.error(e)
    if not other_user:
        abort(404)
    # 判断当前登录用户是否关注此用户
    is_followed = False
    if user:
        if other_user.followers.filter(User.id == user.id).count() > 0:
            is_followed = True
    context = {
        'user': user.to_dict(),
        'other_user': other_user.to_dict(),
        'is_followed': is_followed
    }
    return render_template('news/other.html', context=context)


@user_blue.route('/other_news_list')
def other_news_list():
    """其他用户发布新闻列表"""
    # 获取页数
    page = request.args.get("p", 1)
    user_id = request.args.get("user_id")
    try:
        page = int(page)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    if not all([page, user_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    try:
        user = User.query.get(user_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据查询错误")

    if not user:
        return jsonify(errno=RET.NODATA, errmsg="用户不存在")

    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.OTHER_NEWS_PAGE_MAX_COUNT,
                                                                       False)
        # 获取当前页数据
        news_li = paginate.items
        # 获取当前页
        current_page = paginate.page
        # 获取总页数
        total_page = paginate.pages
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据查询错误")

    news_dict_li = []

    for news_item in news_li:
        news_dict_li.append(news_item.to_review_dict())
    data = {
        "news_list": news_dict_li,
        "total_page": total_page,
        "current_page": current_page
    }
    return jsonify(errno=RET.OK, errmsg="OK", data=data)
